<?php

/*
 * 方法名为ad_xxx 为LJC编写
 */
namespace Common\Controller;
class CaijiContrller {
    
    private $html='';             //远程文件读取内容
    private $data=array();        //返回内容
    private $regExtArray=array();
    private $type=1;              //1:内容采集；2：列表采集

    /*
     * 构造函数
     * 传入URL
     * regExtArray  自定义结果过滤数组
     * $type  1:内容采集；2：列表采集
     * $ext   必须，采集目标正则集合  array
     */
    public function __construct($url,$ext,$type=1,$regExtArray=array()) {
        if(empty($url)){
            echo '采集目标地址必须！';
            exit();
        }
        if(empty($ext)){
            echo '采集内容规则必须！';
            exit();
        }
        $this->type=$type;
        $this->regExtArray=$regExtArray;
        $this->readHtml($url);               //读文件
        $this->code();                       //转字符集
        $this->ad_formatEnCodeTime();        //格式化时间
        $this->filterScript();               //处理JS代码
        $this->ad_format();                  //格式化代码
        $this->ad_formatDeCodeTime();        //解析时间格式 
        switch ($type) {
            case 1:    //采集内容
                $this->regx_once($ext);
                break;
            case 2:    //采集列表
                $this->regx_all($ext);
                break;
        }
    }
    
    
    /*
     * 读取远程文件
     */
    
    private function readHtml($url){
        $html= file_get_contents($url);       //基本方法读取，读取失败使用curl读取
        if(empty($html)){
            $ch = curl_init();
            curl_setopt ($ch,CURLOPT_URL,$url);
            curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
            curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");
            $html = curl_exec($ch);
            curl_close( $ch );
        }
        if(empty($html)){
            echo '读取远程文件失败！';
            exit();
        }
        $this->html=$html;
    }
    
    
    /*
     * 转换字符集
     * 目标编码为utf8
     */
    private function code(){
        
        $type=  mb_detect_encoding($this->html, array('UTF-8','GBK','LATIN1','BIG5'));
        if($type!= 'UTF-8'){
            $this->html=  mb_convert_encoding($this->html,'utf-8',$type);
        }
    }
    
    
    /*
     * 格式化时间
     */
    private function ad_formatEnCodeTime(){
        $this->html = preg_replace('~(\d{4})(\-|\/){1}(\d{2})(\-|\/){1}(\d{2})\s+(\d{2})\:(\d{2})~is','$1$2$3$4$5@$6:$7',$this->html);
    }
    
    /*
     * 解析时间
     */
    private function ad_formatDeCodeTime(){
        $this->html = preg_replace('~(\d{4})(\-|\/){1}(\d{2})(\-|\/){1}(\d{2})\@+(\d{2})\:(\d{2})~is','$1$2$3$4$5 $6:$7',$this->html );
    }
    
    /*
     *处理JS代码
     */
    private function filterScript( ){
        $this->html = preg_replace('~\<(script.*?)\>(.*?)\<(\/script.*?)\>~is','',$this->html );
    }
    
    
    
    /*
     * 格式化代码
     */
    private function ad_format(){
        $segments = preg_split("/(<[^>]+?>)/si",$this->html, -1,PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
        $compressed = array();
        $stack = array();
        $tag = '';
        $half_open = array('meta','input','link','img','br');
        $cannot_compress = array('pre','code','script','style');
        foreach($segments as $seg){
            if(trim($seg) === ''){continue;}
            if(preg_match("!<([a-z0-9]+)[^>]*?/>!si",$seg, $match)){
                $compressed[] = $seg;
            }else if(preg_match("!</([a-z0-9]+)[^>]*?>!si",$seg,$match)){
                $tag = trim( strtolower( $match[1] ) );
                if(count($stack) > 0 && $stack[count($stack)-1] == $tag){
                    array_pop($stack);
                    $compressed[] = $seg;
                }
            }else if(preg_match("!<([a-z0-9]+)[^>]*?>!si",$seg,$match)){
                $tag =  trim( strtolower( $match[1] ) );
                if(!in_array($tag, $half_open)){
                    array_push($stack,$tag);
                }
                $compressed[] = $seg;
            }else if(preg_match("~<![^>]*>~", $seg)){
                $compressed[] = $seg;
            }else{
                $compressed[] = in_array($tag, $cannot_compress) ? $seg : preg_replace('!\s!', '', $seg);
            }
        }
        $compressed = join('',$compressed);
        $this->html = str_replace( array( "\t", "\r\n", "\r", "\n", "&nbsp;", "　" ), "", $compressed );
    }
    
    /*
     * 正则获取内容
     * 非preg_match_all模式
     */
    public function regx_once($regx=array()){
        foreach($regx as $key=>$val){
            $val=  htmlspecialchars_decode($val);
            $html=$this->html;
            if(empty($val)){
                
                continue;
            }
            
            if(is_string($val)){
                    preg_match($val,$html,$array);
                    $html=end($array);
            }elseif(is_array($val)){
                foreach ($val as $rgx){
                    preg_match($rgx,$html,$array);
                    $html=end($array);
                }
            }
            $this->data[$key]=$html;
            unset($html);
        }
    }
    
    /**/
    private function getDate(){
        $patterns=array(0=>'/年/',1=>'/月/',2=>'/日/',3=>'/时/',4=>'/分/',5=>'/秒/');
        $replacements=array(0=>'-',1=>'-',2=>' ',3=>':',4=>':',5=>'');
        $this->data['date']= preg_replace($patterns, $replacements, $this->data['date']);
    }
    
    public function regx_all($regx=array(),$html='',$num=0){
            if(empty($html)){
                $html=$this->html;
            }
            if(count($regx)-1 >$num){
                preg_match_all($regx[$num], $html, $array);
                $num+=1;
                foreach($array[1] as $val){
                    $return=$this->regx_all($regx, $val, $num);
                }
            }else{
                preg_match_all($regx[$num], $html, $array);
                $this->data= array_merge($this->data,$array[1]);
            }
            return ;
    }
    
    /*
     * 获取采集后的内容
     */
    public function getData(){
        if(isset($this->data['date'])){
            $this->getDate();
        }
        if($this->type === 1){
            foreach($this->data as $key =>$val){
                 $this->data[$key]=$this->ad_baseFilter($val);
            }
        }
        return $this->data;
    }
    
    
    /*
     * 结果集过滤数据
     */    
    private function ad_baseFilter($str){
        // 过滤所有属性
        $str = preg_replace('~\<(img|IMG)~is','<@@@',$str);
        $str = preg_replace('~<(\w+?)\s+?.*?>~is','<$1>',$str);
        $str = preg_replace('~\<@@@~is','<img',$str);
        $regArray = array(
            '~\<\s*br[\s\/]*\>~is',
            '~\s(align|alt|class|width|height)\=((\w+)|([\'\"]+[\'\"]+)|[\'\"]+.*?[\'\"]+)*~is',
            '~\<\!\-\-\s*.*?\s\-\-\>~is'
        );
        // 合并扩展
        $str= preg_replace( array_merge( $regArray, $this->regExtArray), "", $str );

        //替换标签
        $str = preg_replace( '~<\s*(\/)*\s*(h\d+|div|center)\s*\/*\s*\>~is', '<$1p>', $str );

        //替换空标签
        do{
            $ext = '/\<(h\d+|samp|span|strong|b|a|div|p|em|font|i|table|td|tr|tbody|thead|tfoot|ul|li|ol|dt|dd|dl)\>\<\/(h\d+|samp|span|strong|b|a|div|p|em|font|i|table|td|tr|tbody|thead|tfoot|ul|li|ol|dt|dd|dl)\>/is';
            $startStrlen=  strlen($str);
            $str = preg_replace( $ext, '', $str );
        }while ($startStrlen !== strlen($str));
        return $str;
    }
}
